package com.sleepingrain;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;

public class WaveActivity extends SoundActivity implements SeekBar.OnSeekBarChangeListener
{	
	private final int DEFAULT_VOLUME = 75;
	private final int DEFAULT_TREBLE = 50;
	private final int DEFAULT_BASS = 50;
	
	private final int DEFAULT_HEIGHT = 50;
	private final int DEFAULT_INTERVAL = 50;
	private final int DEFAULT_INTENSITY = 25;
	private final int DEFAULT_SEAGULL = 25;
	
	private SeekBar sbVolume;
	private SeekBar sbIntensity;
	private SeekBar sbHeight;
	private SeekBar sbInterval;
	private SeekBar sbTreble;
	private SeekBar sbBass;
	private SeekBar sbSeaGull;
	
	private WaveGenerator mWaveGenerator;
	private SeaGullGenerator mSeaGullGenerator;
	private ExecutorService mExecutor;
	Thread mWaveSampleCreator;
	Thread mSeaGullSampleCreator;
	
	// ------------------- sound activity section ------------------- //
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{	
		super.onCreate(savedInstanceState);
		setContentView(R.layout.wave);
		initSoundUI();
		
		mExecutor = Executors.newCachedThreadPool();
		mWaveGenerator = new WaveGenerator(soundBuffer, createWaveSampleLib());
		mSeaGullGenerator = new SeaGullGenerator(soundBuffer, createSeaGullSampleLib());
		
		loadWaveSettings();
		initializeSeekbars();
		initializeIconViews();
	}
	
	/**
	 * Function to create the wave sample lib
	 * @return the wave sample lib
	 */
	public SampleLib createWaveSampleLib()
	{
		// Load the main sample from assets
		final SampleLib waveLib = new SampleLib(); 	
		waveLib.loadFromAssets(getAssets(), "Wave", 44100, 2);
		
		
		mWaveSampleCreator = new Thread( new Runnable() {
			public void run() {
				Thread.currentThread().setName("CreateWaveSampleLib");
				Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
				
				// Generate samples
				List<Sample> originals = waveLib.getOriginals();
				waveLib.addAll(Sample.resampleBy(originals, 30, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 45, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 60, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 75, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 90, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 115, 3));
				SortSampleList(waveLib);
				waveLib.addAll(Sample.resampleBy(originals, 130, 3));
				SortSampleList(waveLib);;
			}
		});
		mWaveSampleCreator.setName("mWaveSampleCreator");
		mWaveSampleCreator.setPriority(Thread.MIN_PRIORITY);
		mWaveSampleCreator.start();
		return waveLib;
	}
	
	private void SortSampleList(SampleLib waveLib)
	{
		Collections.sort(waveLib, new Comparator<Object>() {
		    public int compare(final Object o1, final Object o2) {
		        final Sample s1 = (Sample) o1;
		        final Sample s2 = (Sample) o2;
		        final Integer i1 = new Integer(((Sample) s1).samples.length);
		        final Integer i2 = new Integer(((Sample) s2).samples.length);
		        return i1.compareTo(i2);
		    }
		});
	}
	
	/**
	 * Function to create the sea gull sample lib
	 * @return the sea gull sample lib
	 */
	public SampleLib createSeaGullSampleLib()
	{
		// Load the main sample from assets
		final SampleLib seaGullLib = new SampleLib(); 		
		seaGullLib.loadFromAssets(getAssets(), "SeaGull", 44100, 1);
			
		// Generate samples
		
			mSeaGullSampleCreator = new Thread(new Runnable() {
			public void run() {
				Thread.currentThread().setName("CreateSeaGullSampleLib");
				Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
				List<Sample> originals = seaGullLib.getOriginals();
				seaGullLib.addAll(Sample.resampleBy(originals, 80, 3));
				seaGullLib.addAll(Sample.resampleBy(originals, 85, 3));
				seaGullLib.addAll(Sample.resampleBy(originals, 90, 3));
				seaGullLib.addAll(Sample.resampleBy(originals, 95, 3));
			}
		});
		mSeaGullSampleCreator.setName("SeaGullSampleCreator");	
		mSeaGullSampleCreator.setPriority(Thread.MIN_PRIORITY);
		return seaGullLib;
	}
	
	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#onStop()
	 */
	@Override
	protected void onStop() {
		super.onStop();
		mExecutor.shutdownNow();
	}

	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#onStart()
	 */
	@Override
	protected void onStart() {
		if(mExecutor == null)
			mExecutor = Executors.newCachedThreadPool();	
		mExecutor.execute(mWaveGenerator);
		mExecutor.execute(mSeaGullGenerator);
		mExecutor.execute(soundPlayer);
		super.onStart();
	}

	/* (non-Javadoc)
	 * @see android.app.Activity#onPause()
	 */
	@Override
	protected void onPause() {
		super.onPause();
		saveWaveSettings();
	}
	
	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#startPlayer()
	 */
	@Override
	public void startPlayer() {
		ivIcon.setImageResource(R.drawable.ic_wave_pause);
		super.startPlayer();
	}

	/* (non-Javadoc)
	 * @see com.sleepingrain.SoundActivity#stopPlayer()
	 */
	@Override
	public void stopPlayer() {
		ivIcon.setImageResource(R.drawable.ic_wave_play);
		super.stopPlayer();
	}
	
	
	
	// ------------------- wave activity section ------------------- //
	
	/**
	 * Function to load the settings from the shared preferences
	 */
	public void loadWaveSettings()
	{
		SharedPreferences settings = getSharedPreferences(getClass().getName(), 0);
		
		setVolume(settings.getInt("volume", DEFAULT_VOLUME));
		setTreble(settings.getInt("treble", DEFAULT_TREBLE));
		setBass(settings.getInt("bass", DEFAULT_TREBLE));
		
		mWaveGenerator.setIntensity(settings.getInt("intensity", DEFAULT_INTENSITY));
		mWaveGenerator.setWaveheight(settings.getInt("waveheight", DEFAULT_HEIGHT));
		mWaveGenerator.setInterval(settings.getInt("interval", DEFAULT_INTERVAL));
		mSeaGullGenerator.setSeaGull(settings.getInt("seagull", DEFAULT_SEAGULL));
	}
	
	/**
	 * Function to save the settings to the shared preferences
	 */
	public void saveWaveSettings()
	{
		SharedPreferences.Editor editor = getSharedPreferences(getClass().getName(), 0).edit();
	    editor.putInt("volume", getVolume());
	    editor.putInt("treble", getTreble());
	    editor.putInt("bass", getBass());
	      
	    editor.putInt("intensity", mWaveGenerator.getIntensity());
	    editor.putInt("waveheight", mWaveGenerator.getWaveheight());
	    editor.putInt("interval", mWaveGenerator.getInterval());
	    editor.putInt("seagull", mSeaGullGenerator.getSeaGull());
	 	      
	    // Commit the edits!
	    editor.commit();
	}
	
	
	// ------------------- seek bar section ------------------- //
	
	/**
	 * Function to initialize the used seek bars
	 */
	protected void initializeSeekbars()
	{

		sbVolume = (SeekBar)findViewById(R.id.sbVolume);
		sbVolume.setOnSeekBarChangeListener(this);
		sbVolume.setProgress(getVolume());
		
		sbTreble = (SeekBar)findViewById(R.id.sbTreble);
		sbTreble.setOnSeekBarChangeListener(this);
		sbTreble.setProgress(getTreble());
		
		sbBass = (SeekBar)findViewById(R.id.sbBass);
		sbBass.setOnSeekBarChangeListener(this);
		sbBass.setProgress(getBass());
		
		sbHeight = (SeekBar)findViewById(R.id.sbHeight);
		sbHeight.setOnSeekBarChangeListener(this);
		sbHeight.setProgress(mWaveGenerator.getWaveheight());
		
		sbInterval = (SeekBar)findViewById(R.id.sbIntervall);
		sbInterval.setOnSeekBarChangeListener(this);
		sbInterval.setProgress(mWaveGenerator.getInterval());
		
		sbIntensity = (SeekBar)findViewById(R.id.sbIntensity);
		sbIntensity.setOnSeekBarChangeListener(this);
		sbIntensity.setProgress(mWaveGenerator.getIntensity());
		
		sbSeaGull = (SeekBar)findViewById(R.id.sbSeagull);
		sbSeaGull.setOnSeekBarChangeListener(this);
		sbSeaGull.setProgress(mSeaGullGenerator.getSeaGull());
	}

	
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
		showToast(seekBar.getProgress()+" %");

		switch(seekBar.getId()) {
			case R.id.sbVolume: setVolume(progress); break;
			case R.id.sbTreble: setTreble(progress); break;
			case R.id.sbBass: setBass(progress); break;
		}
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {
		switch(seekBar.getId())
		{
			case R.id.sbHeight:
				mWaveGenerator.setWaveheight(seekBar.getProgress());
				break;
			case R.id.sbIntervall:
				mWaveGenerator.setInterval(seekBar.getProgress());
				break;
			case R.id.sbIntensity:
				mWaveGenerator.setIntensity(seekBar.getProgress());
				break;			
			case R.id.sbSeagull:
				mSeaGullGenerator.setSeaGull(seekBar.getProgress());
				break;
		}
	}

	
	// ------------------- icon view section ------------------- //

	/**
	 * Function to initialize the icon views 
	 * Call after initializeSeekbars()
	 */
	public void initializeIconViews()
	{
		ImageView iv = (ImageView)findViewById(R.id.ivVolume);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				setVolume(DEFAULT_VOLUME);
				sbVolume.setProgress(DEFAULT_VOLUME);
			}
		});
		
		iv = (ImageView)findViewById(R.id.ivTrebleBass);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				setTreble(DEFAULT_TREBLE);
				setBass(DEFAULT_BASS);
				sbTreble.setProgress(DEFAULT_TREBLE);
				sbBass.setProgress(DEFAULT_BASS);
			}
		});
		
		iv = (ImageView)findViewById(R.id.ivIntensity);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				mWaveGenerator.setIntensity(DEFAULT_INTENSITY);
				sbIntensity.setProgress(DEFAULT_INTENSITY);
			}
		});
		
		iv = (ImageView)findViewById(R.id.ivInterfal);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				mWaveGenerator.setIntensity(DEFAULT_INTERVAL);
				sbInterval.setProgress(DEFAULT_INTERVAL);
			}
		});
		
		iv = (ImageView)findViewById(R.id.ivHeight);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				mWaveGenerator.setIntensity(DEFAULT_HEIGHT);
				sbHeight.setProgress(DEFAULT_HEIGHT);
			}
		});
		
		iv = (ImageView)findViewById(R.id.ivSeaGull);
		iv.setOnClickListener(new View.OnClickListener() {	
			@Override
			public void onClick(View v) {
				mSeaGullGenerator.setSeaGull(DEFAULT_SEAGULL);
				sbSeaGull.setProgress(DEFAULT_SEAGULL);
			}
		});
	}
}

